package com.miyake.dsp.osa.lab;

import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.zip.CRC32;

import com.miyake.dsp.ComplexArray;

public class Connector {

	public boolean isNowRequesting() {
		return nowRequesting;
	}

	interface InputListener {
		public void onDataUpdate(Connector connector);
	};
	interface OutputListener {
		public void onDataRequest();
	};
	private List<InputListener> inputListeners = new ArrayList<InputListener>();
	private List<OutputListener> outputListeners = new ArrayList<OutputListener>();
	private boolean nowRequesting;
	private boolean loaded;
	private String code;
	
	public void addInputListener(InputListener listener) {
		inputListeners.add(listener);
	}
	
	public void removeInputListener(InputListener listener) {
		inputListeners.remove(listener);
	}
	
	public void addOutputListener(OutputListener listener) {
		outputListeners.add(listener);
	}	
	
	public void removeOutputListener(OutputListener listener) {
		outputListeners.remove(listener);
	}
	
	protected void fireDataUpdate(String key, final ComplexArray data) {
		// In case this class requests calculation to source calculator, 
		// does not inform updating to sink calculator, 
		// so that the sink calculator does not calculate twice.
		if (!nowRequesting) { 
			for (final InputListener listener : inputListeners) {
				listener.onDataUpdate(this);
/*
				new Thread() {
					@Override
					public void run() {
						listener.onDataUpdate(data);
					}
				}.start();
*/
			}
		}
	}
	protected void fireDataRequest() {
		for (OutputListener listener : outputListeners) {
			listener.onDataRequest();
		}
	}
	public String getKey() {
		return key;
	}

	private String key;
	private ComplexArray data;
	private LabContainer parent;
	
	public LabContainer getParent() {
		return parent;
	}

	public void setParent(LabContainer parent) {
		this.parent = parent;
	}
	
	public Connector(double[] t) {
		setData(t);
	}
	
	public Connector(LabContainer parent, String key) {
		this.parent = parent;
		this.key = key;
	}
	
	public void setData(double[] t) {
		this.data = new ComplexArray(t);
		loaded = true;
		//fireDataUpdate(this.data);
	}
	
	public void setData(ComplexArray c) {
		if (c != null) {
			this.code = new MyCheckSum(c).getCode();
		}
		this.data = c;
		loaded = true;
		//System.out.println(this.key + ":" + this.code);
		//fireDataUpdate(this.data);
	}
	
	public ComplexArray getData() {
		return getData(true);
	}
	
	public ComplexArray getData(boolean requestEnabled) {
		if (this.data == null && requestEnabled) {
			nowRequesting = true;
			fireDataRequest();
			nowRequesting = false;
		}
		return this.data;
	}

	public boolean isEmpty() {
		if (this.data == null) {
			return true;
		}
		return false;
	}
	
	public void clear() {
		this.data = null;
	}
	
	public void fire() {
		if (loaded) {
			this.fireDataUpdate(key, data);
			loaded = false;
		}
	}

	public String getCode() {
		return this.code;
	}
}
